import { char_dict, full_dict, polyphone } from './pinyin.config'
/**
 * @typedef Option
 * @type Object
 * @property {Boolean} [checkPolyphone=false] 是否检查多音字
 * @property {Number} [charCase='titlecase'] 输出拼音的大小写模式，titlecase-首字母大写；lowercase-全小写；uppercase-全大写
 */
interface Options {
  checkPolyphone?: boolean
  charCase?: 'titlecase' | 'lowercase' | 'uppercase'
}
class Pinyin {
  options: Options = {}
  /**
   * 构造函数，设置参数并初始化数据
   * @param {Option} [options] 参数对象
   */
  constructor(options: Options) {
    this.setOptions(options)
  }

  /**
   * 设置参数
   * @param {Option} [options] 参数对象
   */
  setOptions(options) {
    options = options || {}
    this.options = Object.assign(
      { checkPolyphone: false, charCase: 'titlecase' },
      options
    )
  }
  /**
   * 获取拼音首字母
   * @param {String} str 输入的中文字符串
   */
  getCamelChars(str: string) {
    let chars = new Array() //保存中间结果的数组
    for (let i = 0, len = str.length; i < len; i++) {
      //获得unicode码
      let ch = str.charAt(i)
      //检查该unicode码是否在处理范围之内,在则返回该码对映汉字的拼音首字母,不在则调用其它函数处理
      chars.push(this._getChar(ch))
    }
    //处理arrResult,返回所有可能的拼音首字母串数组
    let result = this._getResult(chars)

    this.options.charCase === 'lowercase'
      ? (result = result.toLowerCase())
      : this.options.charCase === 'uppercase'
      ? (result = result.toUpperCase())
      : {}
    return result
  }

  /**
   * 获取拼音
   * @param {String} str 输入的中文字符串
   */
  getFullChars(str: string) {
    let len = str.length
    let result = ''
    let reg = new RegExp('[a-zA-Z0-9- ]')
    for (let i = 0; i < len; i++) {
      let ch = str.substr(i, 1)
      let unicode = ch.charCodeAt(0)
      //如果不在汉字处理范围之内,返回原字符,也可以调用自己的处理函数
      if (unicode > 40869 || unicode < 19968) {
        result += ch
      } else {
        let name = this._getFullChar(ch)
        if (name !== false) {
          result += name
        }
      }
    }

    this.options.charCase === 'lowercase'
      ? (result = result.toLowerCase())
      : this.options.charCase === 'uppercase'
      ? (result = result.toUpperCase())
      : {}
    return result
  }

  _getFullChar(ch) {
    for (let key in full_dict) {
      if (full_dict[key].indexOf(ch) != -1) {
        return this._capitalize(key)
        break
      }
    }
    return false
  }

  /**
   * 首字母大写
   */
  _capitalize(str) {
    if (str.length > 0) {
      let first = str.substr(0, 1).toUpperCase()
      let spare = str.substr(1, str.length)
      return first + spare
    }
  }

  _getChar(ch) {
    let unicode = ch.charCodeAt(0)
    //如果不在汉字处理范围之内,返回原字符,也可以调用自己的处理函数
    if (unicode > 40869 || unicode < 19968) return ch //dealWithOthers(ch);
    //检查是否是多音字,是按多音字处理,不是就直接在strChineseFirstPY字符串中找对应的首字母
    if (!this.options.checkPolyphone) return char_dict.charAt(unicode - 19968)
    return polyphone[unicode]
      ? polyphone[unicode]
      : char_dict.charAt(unicode - 19968)
  }

  _getResult(chars) {
    if (!this.options.checkPolyphone) return chars.join('')
    let result = ['']
    for (let i = 0, len = chars.length; i < len; i++) {
      let str = chars[i]
      let strlen = str.length
      if (strlen == 1) {
        for (let j = 0; j < result.length; j++) {
          result[j] += str
        }
      } else {
        let swap1 = result.slice(0)
        result = []
        for (let j = 0; j < strlen; j++) {
          //复制一个相同的arrRslt
          let swap2 = swap1.slice(0)
          //把当前字符str[k]添加到每个元素末尾
          for (let k = 0; k < swap2.length; k++) {
            swap2[k] += str.charAt(j)
          }
          //把复制并修改后的数组连接到arrRslt上
          result = result.concat(swap2)
        }
      }
    }
    return result
  }
}
interface PyOpt {
  opt?: Options
  str: string
  isFull?: Boolean
}
const PY = (opt: PyOpt) => {
  opt = { ...{ opt: {}, isFull: true }, ...opt }
  const newPY = new Pinyin(opt.opt as Options)
  if (opt.isFull) {
    return newPY.getFullChars(opt.str)
  } else {
    return newPY.getCamelChars(opt.str)
  }
}

export default PY
